SparseSoftmaxCrossEntropyWithLogits
计算稀疏标签下的 Softmax 交叉熵损失及梯度。
与 SoftmaxCrossEntropyWithLogits 不同,该算子的标签(Labels)是类别的索引(整数),而不是 One-hot 向量。这通常能节省内存并加速计算。
算法逻辑如下:
Softmax:
\[p_{i,j} = \frac{e^{x_{i,j}}}{\sum_{k} e^{x_{i,k}}}\]
Cross Entropy Loss: 假设 \(y_i\) 为第 \(i\) 个样本的标签索引:
\[loss_i = - \log(p_{i, y_i})\]
Gradients (当 is_grad=1 时):
\[\frac{\partial loss}{\partial x_{i,j}} = p_{i,j} - \mathbb{1}(j == y_i)\]
- 输入:
input - 输入 Logits 地址。形状为 \([N, C]\)。
losses - 输出损失地址。
sum_data - 中间计算缓冲区(Workspace)。
inner_size - 内部维度大小。对于二维输入 \([N, C]\),通常为 1。
outter_size - 外部维度大小。对于二维输入 \([N, C]\),通常为 \(N\) (Batch Size)。
axis_size - 轴维度大小。对于二维输入 \([N, C]\),通常为 \(C\) (Num Classes)。
labels - 标签索引地址。类型为 int,形状为 \([N]\)。
is_grad - 是否计算梯度 (0: 否, 1: 是)。
output - 输出梯度地址。如果
is_grad为 1,则存储计算出的梯度,形状同输入。batch_size - 批大小 (N)。
number_of_classes - 类别数量 (C)。
partial_losses - 中间计算缓冲区(Workspace),用于归约计算。
core_mask - 核掩码(仅适用于共享存储版本)。
- 输出:
losses - 计算得到的交叉熵损失。
output - 计算得到的梯度(若启用)。
- 支持平台:
FT78NEMT7004备注
FT78NE 仅支持 Fp32 数据类型。
MT7004 支持 Fp32 和 FP16 数据类型。
输入数据必须是二维矩阵。
FP16 模式下,labels 依然保持为 int 类型,其余浮点指针变为 float16*。
共享存储版本:
-
void fp_sparse_softmax_cross_entropy_with_logits_s(float *input, float *losses, float *sum_data, uint64_t inner_size, uint64_t outter_size, uint64_t axis_size, int *labels, uint64_t is_grad, float *output, uint64_t batch_size, uint64_t number_of_classes, float *partial_losses, int core_mask)
-
void hp_sparse_softmax_cross_entropy_with_logits_s(float16 *input, float16 *losses, float16 *sum_data, uint64_t inner_size, uint64_t outter_size, uint64_t axis_size, int *labels, uint64_t is_grad, float16 *output, uint64_t batch_size, uint64_t number_of_classes, float16 *partial_losses, int core_mask)
C调用示例(FT78NE - Fp32):
1#include <stdio.h> 2#include <stdint.h> 3 4int main(int argc, char* argv[]) { 5 // 假设所有数据位于 DDR 空间 6 float* input = (float*)0xC0000000; 7 float* losses = (float*)0xC1000000; 8 float* sum_data = (float*)0xC2000000; 9 int* labels = (int*)0xC3000000; 10 float* output = (float*)0xC4000000; 11 float* partial_losses = (float*)0xC5000000; 12 13 uint64_t batch_size = 64; 14 uint64_t number_of_classes = 1000; 15 16 // 针对二维输入 [N, C] 的常用配置 17 uint64_t outter_size = batch_size; 18 uint64_t axis_size = number_of_classes; 19 uint64_t inner_size = 1; 20 21 uint64_t is_grad = 1; // 计算梯度 22 int core_mask = 0xff; 23 24 fp_sparse_softmax_cross_entropy_with_logits_s(input, losses, sum_data, 25 inner_size, outter_size, axis_size, 26 labels, is_grad, output, 27 batch_size, number_of_classes, 28 partial_losses, core_mask); 29 30 return 0; 31}
私有存储版本:
-
void fp_sparse_softmax_cross_entropy_with_logits_p(float *input, float *losses, float *sum_data, uint64_t inner_size, uint64_t outter_size, uint64_t axis_size, int *labels, uint64_t is_grad, float *output, uint64_t batch_size, uint64_t number_of_classes, float *partial_losses)
-
void hp_sparse_softmax_cross_entropy_with_logits_p(float16 *input, float16 *losses, float16 *sum_data, uint64_t inner_size, uint64_t outter_size, uint64_t axis_size, int *labels, uint64_t is_grad, float16 *output, uint64_t batch_size, uint64_t number_of_classes, float16 *partial_losses)
C调用示例(MT7004 - FP16):
1#include <stdio.h> 2#include <stdint.h> 3 4int main(int argc, char* argv[]) { 5 // 假设数据位于 AM 空间 6 float16* input = (float16*)0x10010000; 7 float16* losses = (float16*)0x10020000; 8 float16* sum_data = (float16*)0x10030000; 9 int* labels = (int*)0x10040000; // 标签仍为 int 10 float16* output = (float16*)0x10050000; 11 float16* partial_losses = (float16*)0x10060000; 12 13 uint64_t batch_size = 32; 14 uint64_t number_of_classes = 100; 15 16 uint64_t outter_size = batch_size; 17 uint64_t axis_size = number_of_classes; 18 uint64_t inner_size = 1; 19 20 uint64_t is_grad = 0; // 仅计算 Loss,不计算梯度 21 22 hp_sparse_softmax_cross_entropy_with_logits_p(input, losses, sum_data, 23 inner_size, outter_size, axis_size, 24 labels, is_grad, output, 25 batch_size, number_of_classes, 26 partial_losses); 27 28 return 0; 29}